/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 * Licensed under the Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *     http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "scp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <securec.h>

#include "portal.h"

static int SendContainerMsg(const struct TeePortalContainerType *config, struct TeePortalType *portal, uint32_t mode)
{
    int ret = -1;
    struct TeePortalType *scp = (struct TeePortalType *)portal;

    scp->type = SEND_CONTAINER_MSG;
    scp->reeUID = getuid();
    scp->sessionID = 0;
    scp->args.containerMsg.mode = mode;
    scp->nsId = config->nsid;

    if (memcpy_s(scp->args.containerMsg.containerId, sizeof(scp->args.containerMsg.containerId),
                 config->containerid, CONTAINER_ID_LEN) != 0) {
        printf("strncpy_s failed\n");
        return -EFAULT;
    }
    ret = TriggerPortal();
    if (ret != 0)
        printf("trigger portal is not successful!\n");

    return ret;
}

int TeeClean(int grpId)
{
    int ret = -1;
    uint32_t portalSize;
    struct TeePortalType *portal = NULL;

    if (grpId < 0) {
        printf("illegal group id!\n");
        return ret;
    }

    if (GetPortal((void**)&portal, &portalSize) != 0) {
        printf("get portal failed\n");
        return -EFAULT;
    }

    portal->type = CLEAN;
    portal->reeUID = getuid();
    portal->sessionID = 0;
    portal->args.clean.grpId = grpId;
    printf("In TeeClean, grpid is %d\n", grpId);
    ret = TriggerPortal();
    if (ret != 0) {
        printf("trigger portal failed\n");
        return ret;
    }

    if (portal->ret != 0) {
        ret = portal->ret;
    }

    return ret;
}

int TeeRconfig(struct TeePortalRConfigType *config, long nsid)
{
    int ret = -1;
    if (config == NULL) {
        printf("Unexpected null pointer for resource limit!\n");
        return ret;
    }

    uint32_t portalSize;
    struct TeePortalType *portal = NULL;

    if (GetPortal((void**)&portal, &portalSize) != 0) {
        printf("get portal failed\n");
        return -EFAULT;
    }

    portal->type = RCONFIG;
    portal->reeUID = getuid();
    portal->sessionID = 0;
    portal->nsId = (uint32_t)nsid;
    portal->args.rconfig.vmid = config->vmid;

    if (strcpy_s(portal->args.rconfig.cpus, PARAM_LEN, config->cpus) != 0) {
        printf("failed to copy mem size!\n");
        return -EFAULT;
    }

    if (strcpy_s(portal->args.rconfig.memSize, PARAM_LEN, config->memSize) != 0) {
        printf("failed to copy mem size!\n");
        return -EFAULT;
    }

    if (strcpy_s(portal->args.rconfig.diskSize, PARAM_LEN, config->diskSize) != 0) {
        printf("failed to copy disk mem size!\n");
        return -EFAULT;
    }

    if (strcpy_s(portal->args.rconfig.cpuset, PARAM_LEN, config->cpuset) != 0) {
        printf("failed to copy cpuset size!\n");
        return -EFAULT;
    }

    ret = TriggerPortal();
    if (ret != 0) {
        printf("trigger portal failed\n");
        return -1;
    }
    printf("online cpuset: %s\n", portal->args.rconfig.onlineCpus);

    /* portal->ret is group id for ree container */
    return portal->ret;
}


int TeeSendContainerMsg(const struct TeePortalContainerType *config, uint32_t mode)
{
    if (config == NULL) {
        printf("send container msg failed\n");
        return -EINVAL;
    }
    int ret = 0;
    uint32_t portalSize;
    struct TeePortalType *portal = NULL;

    if (GetPortal((void**)&portal, &portalSize) != 0) {
        printf("get portal failed\n");
        return -EFAULT;
    }

    if (SendContainerMsg(config, portal, mode) != 0) {
        printf("The send container msg execution is not successful!\n");
        return -EFAULT;
    }

    if (portal->ret != 0) {
        printf("The execution result of the portal is %d!\n", portal->ret);
        ret = portal->ret;
    }
    return ret;
}